package com.tiendung.otalunch;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.DatePicker;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.Toast;

public class Today extends Activity {
	
	public ExpandableListAdapter adapter;
	private boolean isUsingLocation = false;
	private ArrayList<Food> foodlist = null;
	public ExpandableListView expendableListView;	

	private int mDay;
	private int mMonth;
	private int mYear;
	private int mPrevDay;
	private int mPrevMonth;
	private int mPrevYear;
	static final int DATE_DIALOG_ID = 0;
	private DatePickerDialog datePickerDialog;
	private boolean wasShown = false;
	
	static final int LOCATION = 0;
	static final int RATE = 1;
	static final int PLAN_TO_GO = 2;
	static final int CHECK_FRIEND = 3;

	private OtaLunchDatabase db;
    public String strName;
	public String strRestaurant;
	public int iRating;
	
	MyLocationListener mNetworkListener;
	double current_lat;
	double current_long;
	private class MyLocationListener implements LocationListener 
    {			
		public MyLocationListener()
		{
			current_lat = -200.0;
			current_long = -200.0;
		}
				
		@Override
		public void onLocationChanged(Location location) {
			makeUseOfNewLocation(location);
		}

		public void onProviderDisabled(String provider) {}

		@Override
		public void onProviderEnabled(String provider) {}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {}
		
		public void makeUseOfNewLocation(Location location) {
			current_lat = location.getLatitude();
			current_long = location.getLongitude();
		}
    };
    
    public Handler handler = new Handler()      
    {            
    	@Override          
    	public void handleMessage(Message msg)          
    	{              
    		adapter.notifyDataSetChanged();              
    		super.handleMessage(msg);          
    	}        
    };  
	
	private DatePickerDialog.OnDateSetListener mDateSetListener = 
		new DatePickerDialog.OnDateSetListener() {                
			public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) 
			{                    
				// the current date should be written into the database and compare onResume()
				mYear = year;                    
				mMonth = monthOfYear;                    
				mDay = dayOfMonth;
				TheTabWidget.mDay = mDay;
				TheTabWidget.mMonth = mMonth;
				TheTabWidget.mYear = mYear;
				
				if ((mPrevDay != mDay) || (mPrevMonth != mMonth) || (mPrevYear != mYear)) {
					mPrevDay = mDay;
					mPrevMonth = mMonth;
					mPrevYear = mYear;
										
					getFoodList();
				}
			}            
		};
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.today);
        
        this.db = new OtaLunchDatabase(this);
                
        // set the current date value
        // the current date should be written into the database and compare onResume()
        mDay = TheTabWidget.mDay;
        mMonth = TheTabWidget.mMonth;
        mYear = TheTabWidget.mYear;        
        mPrevDay = mDay;
        mPrevMonth = mMonth;
        mPrevYear = mYear;
        datePickerDialog = new DatePickerDialog(this, mDateSetListener, TheTabWidget.mYear, TheTabWidget.mMonth, TheTabWidget.mDay);    
        
        expendableListView = (ExpandableListView) findViewById(R.id.expendableListView);   
        registerForContextMenu(expendableListView);
        this.getFoodList();
        
    }
    
    @Override
    public void onResume() {
    	super.onResume();
    	
    	mDay = TheTabWidget.mDay;
        mMonth = TheTabWidget.mMonth;
        mYear = TheTabWidget.mYear; 
        
        
        if ((mPrevDay != mDay) || (mPrevMonth != mMonth) || (mPrevYear != mYear)) {
			mPrevDay = mDay;
			mPrevMonth = mMonth;
			mPrevYear = mYear;
			
			getFoodList();
		}
        
        if (wasShown)
        	datePickerDialog.updateDate(mYear, mMonth, mDay);     
    }
    
    private String getCurrentLocation() {
    	LocationManager mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);	
		mNetworkListener = new MyLocationListener();
		
		mlocManager.removeUpdates(mNetworkListener);
		mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mNetworkListener);
		mlocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mNetworkListener);
		
		if (mlocManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
		{
			while (current_lat < -180.0 && current_long < -180.0) {}
			mlocManager.removeUpdates(mNetworkListener);
			
			return new String("&lat=" + current_lat + "&long=" + current_long);
		}
		else
		{
			return new String("&lat=60.187375&long=24.822357");
		}
		
    }
    
    public void getFoodList() {
    	adapter = new ExpandableListAdapter(this, new ArrayList<String>(), new ArrayList<ArrayList<Food>>());            
    	foodlist = new ArrayList<Food>();

    	if (!isUsingLocation)
	    	// query from local database
	    	if (!getFood(mDay, mMonth, mYear, foodlist))
	    	{
		    	// if local database is empty, query from internet
	    		final String url = "http://" + TheTabWidget.serverIP + "/foodlist.php?day=" + this.mDay + "&month=" + (this.mMonth + 1) + "&year=" + this.mYear; 
		    	
		    	final ProgressDialog dialog = ProgressDialog.show(Today.this, "", "Downloading. Please wait...", true);    	
		    	new Thread(new Runnable() 
		        {    
		    		public void run() {    
		
		        		getFoodListFromNetwork(url);
		        		
		        		// Set the adapter to the view and notify the adapter
		        		expendableListView.post(new Runnable() {
		        			public void run() {  
	        					expendableListView.setAdapter(adapter);
	        			    	handler.sendEmptyMessage(1);
		        			}      
		        		});  
		        			            
		                
		                dialog.cancel();
		        	}  
		        }).start();  
	    	}
	    	else
	    	{
	    		ProgressDialog dialog = ProgressDialog.show(Today.this, "", "Downloading. Please wait...", true);    	
	    		
	    		expendableListView.post(new Runnable() {
	    			public void run() {  
	    				expendableListView.setAdapter(adapter);
	    		    	handler.sendEmptyMessage(1);
	    			}      
	    		});  
	    			            
	            dialog.cancel();
	    	}
    	else
    	{
    		final String url = "http://" + TheTabWidget.serverIP + "/foodlist_location.php?day=" + this.mDay + "&month=" + (this.mMonth + 1) + "&year=" + this.mYear + getCurrentLocation();
	    	
	    	final ProgressDialog dialog = ProgressDialog.show(Today.this, "", "Downloading. Please wait...", true);    	
	    	new Thread(new Runnable() 
	        {    
	    		public void run() {    
	
	        		getFoodListFromNetwork(url);
	        		
	        		// Set the adapter to the view and notify the adapter
	        		expendableListView.post(new Runnable() {
	        			public void run() {  
        					expendableListView.setAdapter(adapter);
        			    	handler.sendEmptyMessage(1);
	        			}      
	        		});  
	        			            
	                
	                dialog.cancel();
	        	}  
	        }).start();
    	}
    	
    }
    
    private boolean getFood(int day, int month, int year, ArrayList<Food> list) 
    {
    	ArrayList<HashMap<String, String>> foodlist = db.select_food(day, month + 1, year);
    	
    	if (foodlist.get(0).get("name") != null)
    	{
        	Food temp;
    		for (int i = 0; i < foodlist.size(); i++)
    		{
    			temp = new Food(foodlist.get(i).get("name"), foodlist.get(i).get("restaurant"), Integer.parseInt(foodlist.get(i).get("rating")));
    		
				HashMap<String, Integer> hm = adapter.addItem(temp);
				temp.setGroup(hm.get("Group"));
	        	temp.setChild(hm.get("Child"));
	        	list.add(temp);
    		}
    		
    		return true;
    	}
    	else return false;
    }
    
    private void saveFood(int day, int month, int year, Food food)
    {
    	month = month + 1;
		db.insert_food(day, month, year, food.getName(), food.getRestaurant(), food.getRate());
    }
    
    private void getFoodListFromNetwork(String url) 
    {
    	try
    	{
			DefaultHttpClient client = new DefaultHttpClient();
	    	HttpGet request = new HttpGet(url);	
	    	HttpResponse response = client.execute(request);
	    	
	    	if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) 
	    	{
	    		InputStream is = response.getEntity().getContent();
	            	            
	            SAXParserFactory spf = SAXParserFactory.newInstance();
	            SAXParser sp = spf.newSAXParser();				
				
	            // SAX Parser handler
	            DefaultHandler handler = new DefaultHandler() {
					private boolean name = false;
					private boolean rating = false;
					private boolean restaurant = false;
					private boolean today = false;
					
					public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException 
					{						
						if (qName.equalsIgnoreCase("today")) {
							today = true;
						}
						
						if (qName.equalsIgnoreCase("tomorrow")) {
							today = false;
						}
						
						if (qName.equalsIgnoreCase("restaurant")) {
							restaurant = true;
						}
						
						if (qName.equalsIgnoreCase("name")) {
							name = true;
						}
												
						if (qName.equalsIgnoreCase("rating")) {
							rating = true;
						}										
					}
					
					public void characters(char ch[], int start, int length) throws SAXException 
					{
						if (name) {
							strName = new String(ch, start, length);
							name = false;
						}
						
						if (restaurant) {
							strRestaurant = new String(ch, start, length);
							restaurant = false;
						}
												
						if (rating) {
							iRating = Integer.parseInt(new String(ch, start, length).trim());
							rating = false;
							
							Food temp;
							if (today)
							{
								temp = new Food(strName, strRestaurant, iRating);
								if (!isUsingLocation) saveFood(mDay, mMonth, mYear, temp);	
							}
							else
							{
								temp = new Food(strName, strRestaurant, iRating);
								if (!isUsingLocation) saveFood(mDay + 1, mMonth, mYear, temp);
							}
							
							if (today)
		                	{
								HashMap<String, Integer> hm = adapter.addItem(temp);
								temp.setGroup(hm.get("Group"));
					        	temp.setChild(hm.get("Child"));
					        	foodlist.add(temp);
		                	}
			                
						}
					}
	            };
	            
	            sp.parse(is, handler);

	    	}
    	}
    	catch (Exception e) {}
    	
    }
        
    public void changeDate() {
		showDialog(DATE_DIALOG_ID);
    }
    
    @Override
    protected Dialog onCreateDialog(int id) 
    {    
    	switch (id) 
    	{    
    		case DATE_DIALOG_ID:    
    			wasShown = true;
    			return datePickerDialog;
    	}    
    	return null;
    }
       
        
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {    
    	MenuInflater inflater = getMenuInflater();    
    	inflater.inflate(R.menu.setting_menu, menu);    
    	return true;
	}
    
    public void login_facebook() {
    	Intent intent = new Intent(getBaseContext(), FacebookActivity.class);         
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		startActivity(intent);
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {    
    	// Handle item selection    
    	switch (item.getItemId()) 
    	{    
    		case R.id.reminder_list:
    			Toast.makeText(Today.this, "reminder", Toast.LENGTH_LONG).show();
    			return true;
    		case R.id.facebook:
    			login_facebook();
    			return true;
    		case R.id.changedate:
    			this.changeDate();
    			return true;
    		case R.id.use_location:

    			if (!isUsingLocation)
				{
					isUsingLocation = true;    			
					item.setTitle("Stop GPS");
					getFoodList();
				}
				else
				{
					isUsingLocation = false;    			
					item.setTitle("Start GPS");
					getFoodList();
				}
    			
    			return true;
    		default:        
    			return super.onOptionsItemSelected(item);    
    	}
    	
    }
    
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) 
    {  
    	super.onCreateContextMenu(menu, v, menuInfo);  
    	
		ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
		
		int type = ExpandableListView.getPackedPositionType(info.packedPosition);
		
		//Only create a context menu for child items
		if (type == 1) 
		{
			//Array created earlier when we built the expandable list
			menu.setHeaderTitle("Food options");
			menu.add(0, LOCATION, 0, "Restaurant Location");
			menu.add(0, PLAN_TO_GO, 0, "Plan to eat");
			menu.add(0, CHECK_FRIEND, 0, "Friend plan");
			menu.add(0, RATE, 0, "Rate the food");	 
		}
    	
    }
    
    public void mapRestaurant(int groupid, int childid) {

    	Intent intent = new Intent(getBaseContext(), LocationActivity.class);         
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		for (int i = 0; i < foodlist.size(); i++)
			if (foodlist.get(i).getGroup() == groupid && foodlist.get(i).getChild() == childid)
			{
				intent.putExtra("Name", foodlist.get(i).getRestaurant());
				break;
			}
		
		startActivity(intent);
    }
    
    public void rateFood(int groupid, int childid) {

    	Intent intent = new Intent(getBaseContext(), RatingFood.class);         
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		for (int i = 0; i < foodlist.size(); i++)
			if (foodlist.get(i).getGroup() == groupid && foodlist.get(i).getChild() == childid)
			{
				intent.putExtra("Restaurant", foodlist.get(i).getRestaurant());
				intent.putExtra("Name", foodlist.get(i).getName());
				break;
			}
		
		startActivity(intent);
    }
    
    public void bookTime(int groupid, int childid) {
    	Intent intent = new Intent(getBaseContext(), BookingTime.class);         
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		for (int i = 0; i < foodlist.size(); i++)
			if (foodlist.get(i).getGroup() == groupid && foodlist.get(i).getChild() == childid)
			{
				intent.putExtra("Restaurant", foodlist.get(i).getRestaurant());
				intent.putExtra("Name", foodlist.get(i).getName());
				intent.putExtra("Year", this.mYear);
				intent.putExtra("Month", this.mMonth + 1);
				intent.putExtra("Day", this.mDay);
				break;
			}
		
		startActivity(intent);
    }

    public void checkFriend(int groupid, int childid) {
    	Intent intent = new Intent(getBaseContext(), FriendChecking.class);         
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		
		startActivity(intent);
    }
    
    @Override
    public boolean onContextItemSelected(MenuItem item) 
    {
    	ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();
    		 
		int groupPos = 0, childPos = 0;		 
		int type = ExpandableListView.getPackedPositionType(info.packedPosition);
		
		if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) 
		{
			groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
			childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
		}
    		
    	switch (item.getItemId()) {  
	    	case LOCATION:
	    		mapRestaurant(groupPos, childPos);
	    		return true;  
	    	case PLAN_TO_GO:
	    		bookTime(groupPos, childPos);
	    		return true;
	    	case CHECK_FRIEND: 
	    		checkFriend(groupPos, childPos);
	    		return true;
	    	case RATE:   
	    		rateFood(groupPos, childPos);
	    		return true;
	    	default:    
	    		return super.onContextItemSelected(item);  
    	}
    }
    
}